package com.example.demo.jmx; /* JVMCPUUsage
  *
  * Calculate JVM CPU usage on older than JDK version 7 using MXBeans.
  *
  * First initiate MBeanServerConnection using `openMBeanServerConnection` method. Then
  * create proxy connections to MXBeans using `getMXBeanProxyConnections` and after that
  * poll `getJvmCpuUsage` method periodically.
  *
  * JVMCPUUsage is a free Java class:
  * you can redistribute it and/or modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation, either version 3 of the License, or(at your option)
  * any later version. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public License for more details.
  * See COPYING for a copy of the GNU General Public License. If not, see <http://www.gnu.org/licenses/>.
  *
  * Copyright (C) 2017  Lahiru Pathirage <lpsandaruwan@gmail.com> on 3/27/17.
  */

 import com.alibaba.fastjson.JSONObject;

 import javax.management.MBeanServerConnection;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
 import java.io.IOException;
 import java.lang.management.ClassLoadingMXBean;
 import java.lang.management.GarbageCollectorMXBean;
 import java.lang.management.ManagementFactory;
 import java.lang.management.MemoryMXBean;
 import java.lang.management.MemoryPoolMXBean;
 import java.lang.management.MemoryUsage;
 import java.lang.management.OperatingSystemMXBean;
 import java.lang.management.RuntimeMXBean;
 import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
 import java.util.List;


public class JVMCPUUsage {
     // hardcoded connection parameters
     private final String HOSTNAME = "172.36.0.231";
     private final int PORT = 60001;

     private MBeanServerConnection mBeanServerConnection;
     private com.sun.management.OperatingSystemMXBean peOperatingSystemMXBean;
     private OperatingSystemMXBean operatingSystemMXBean;
     private RuntimeMXBean runtimeMXBean;
     private MemoryMXBean memBean;
     private ThreadMXBean threadMXBean;
     private ClassLoadingMXBean classLoadingMXBean;
     // keeping previous timestamps
     private long previousJvmProcessCpuTime = 0;
     private long previousJvmUptime = 0;


     // initiate and prepare MBeanServerConnection
     public void openMBeanServerConnection() throws IOException {
         final String HOSTNAME = "172.36.0.231";
         final int PORT = 60001;
         //1.构建JMX API连接器服务器的初始化地址
         String serviceURL = "service:jmx:rmi:///jndi/rmi://" + HOSTNAME + ":" + PORT + "/jmxrmi";
         JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceURL);

         //2.初始化客户端JMX API连接器,创建与给定地址的连接器服务器的连接。
         JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);

         //3.启动管理bean服务器连接,获取远程MBean服务器的 MBeanServerConnection对象
         //MBeanServerConnection 此接口表示与MBean服务器通信的方式，无论是本地还是远程。 代表本地MBean服务器的MBeanServer接口扩展了此接口。
         MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();

         String[] domains = mBeanServerConnection.getDomains();
         Integer mBeanCount = mBeanServerConnection.getMBeanCount();
         System.out.println(mBeanCount);
     }

     // initiate and prepare MXBean interfaces proxy connections
     public void getMXBeanProxyConnections() throws IOException {

         List<MemoryPoolMXBean> platformMXBeans = ManagementFactory.getPlatformMXBeans(mBeanServerConnection, MemoryPoolMXBean.class);
         List<GarbageCollectorMXBean> platformMXBeans1 = ManagementFactory.getPlatformMXBeans(mBeanServerConnection, GarbageCollectorMXBean.class);
         peOperatingSystemMXBean = ManagementFactory.newPlatformMXBeanProxy(
                 mBeanServerConnection,
                 ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
                 com.sun.management.OperatingSystemMXBean.class
         );
         //获取内存
         memBean=ManagementFactory.newPlatformMXBeanProxy
                 (mBeanServerConnection,ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
         operatingSystemMXBean = ManagementFactory.newPlatformMXBeanProxy(
                 mBeanServerConnection,
                 ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
                 OperatingSystemMXBean.class
         );
         runtimeMXBean = ManagementFactory.newPlatformMXBeanProxy(
                 mBeanServerConnection,
                 ManagementFactory.RUNTIME_MXBEAN_NAME,
                 RuntimeMXBean.class
         );
         threadMXBean = ManagementFactory.newPlatformMXBeanProxy(
                 mBeanServerConnection,
                 ManagementFactory.THREAD_MXBEAN_NAME,
                 ThreadMXBean.class
         );

         ClassLoadingMXBean classLoadingMXBean = ManagementFactory.newPlatformMXBeanProxy(
                 mBeanServerConnection,
                 ManagementFactory.CLASS_LOADING_MXBEAN_NAME,
                 ClassLoadingMXBean.class
         );



         System.out.println(JSONObject.toJSON(classLoadingMXBean));
     }
     // Get JVM bean usage
     public String getJvmBeanUsage() {
         MemoryUsage heap = memBean.getHeapMemoryUsage();
         MemoryUsage nonHeap = memBean.getNonHeapMemoryUsage();
         long heapSizeUsed = heap.getUsed();//堆使用的大小
         long nonHeapSizeUsed = nonHeap.getUsed();
         long heapCommitedSize = heap.getCommitted();
         long nonHeapCommitedSize = nonHeap.getCommitted();
         return String.format("heapSizeUsed:%s,nonHeapSizeUsed:%s,heapCommitedSize:%s,nonHeapCommitedSize:%s",
                 heapSizeUsed,nonHeapSizeUsed,heapCommitedSize,nonHeapCommitedSize);
     }
     // Get JVM CPU usage
     public String getJvmMemUsage() {
         MemoryUsage heap = memBean.getHeapMemoryUsage();
         MemoryUsage nonHeap = memBean.getNonHeapMemoryUsage();
         long heapSizeUsed = heap.getUsed();//堆使用的大小
         long nonHeapSizeUsed = nonHeap.getUsed();
         long heapCommitedSize = heap.getCommitted();
         long nonHeapCommitedSize = nonHeap.getCommitted();

         return String.format("heapSizeUsed:%s,nonHeapSizeUsed:%s,heapCommitedSize:%s,nonHeapCommitedSize:%s",
                 heapSizeUsed,nonHeapSizeUsed,heapCommitedSize,nonHeapCommitedSize);
     }
     // Get JVM CPU usage
     public float getJvmCpuUsage() {
         // elapsed process time is in nanoseconds
         long elapsedProcessCpuTime = peOperatingSystemMXBean.getProcessCpuTime() - previousJvmProcessCpuTime;
         // elapsed uptime is in milliseconds
         long elapsedJvmUptime = runtimeMXBean.getUptime() - previousJvmUptime;

         // total jvm uptime on all the available processors
         long totalElapsedJvmUptime = elapsedJvmUptime * operatingSystemMXBean.getAvailableProcessors();

         // calculate cpu usage as a percentage value
         // to convert nanoseconds to milliseconds divide it by 1000000 and to get a percentage multiply it by 100
         float cpuUsage = elapsedProcessCpuTime / (totalElapsedJvmUptime * 10000F);

         // set old timestamp values
         previousJvmProcessCpuTime = peOperatingSystemMXBean.getProcessCpuTime();
         previousJvmUptime = runtimeMXBean.getUptime();


         return cpuUsage;
     }

    // Get JVM CPU usage
    public void getJvmThreadUsage() {
        System.out.println("以纳秒为单位返回当前线程的总CPU时间。 "+threadMXBean.getCurrentThreadCpuTime());
        System.out.println("返回当前线程以纳秒为单位在用户模式下执行的CPU时间。  "+threadMXBean.getCurrentThreadUserTime());
        System.out.println("返回Java虚拟机启动或峰值复位后的峰值活动线程数."+threadMXBean.getPeakThreadCount());
        System.out.println("返回当前线程数，包括守护进程线程和非守护程序线程数。 "+threadMXBean.getThreadCount());
        System.out.println("返回当前的守护进程线程数。 "+threadMXBean.getDaemonThreadCount());
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
        long[] allThreadIds = threadMXBean.getAllThreadIds();
        System.out.println(allThreadIds.length);
        System.out.println(threadInfos.length);
        for (ThreadInfo threadInfo : threadInfos) {
            System.out.println("getStackTrace:"+threadInfo.getStackTrace());
            System.out.println("getThreadName:"+threadInfo.getThreadName());
            System.out.println("getThreadState:"+threadInfo.getThreadState());
            System.out.println("getWaitedTime:"+threadInfo.getWaitedTime());
            System.out.println("getBlockedTime:"+threadInfo.getBlockedTime());
            System.out.println("getWaitedCount:"+threadInfo.getWaitedCount());
        }
    }


 }